package com.core.util;

import java.beans.PropertyDescriptor;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 公共工具类
 * 
 * @author pt-chenqw
 *
 */
public class CommonUtil {

    private static final Log log = LogFactory.getLog(CommonUtil.class);

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public String stringValue(String v, String def) {
        if (v == null)
            return def;
        return v;
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public byte byteValue(String v, byte def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return Byte.parseByte(v);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public char charValue(String v, char def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return (char) Integer.parseInt(v);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public short shortValue(String v, short def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return Short.parseShort(v);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public int intValue(String v, int def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return Integer.parseInt(v);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public long longValue(String v, long def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return Long.parseLong(v);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public boolean booleanValue(String v, boolean def) {
        if (StringUtils.empty(v))
            return def;

        if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes"))
            return true;
        else if (v.equalsIgnoreCase("false") || v.equalsIgnoreCase("no"))
            return false;
        else
            return def;
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public float floatValue(String v, float def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return Float.parseFloat(v);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 返回两个字符串中的一个，传入值为空时返回默认的
     * 
     * @param v
     *            传入的
     * @param def
     *            默认的
     * @return
     */
    static public double doubleValue(String v, double def) {
        if (StringUtils.empty(v))
            return def;
        try {
            return Double.parseDouble(v);
        } catch (Exception e) {
            return def;
        }
    }

    static public double doubleValue(Double v, double def) {
        if (v == null)
            return 0.0;
        return v.doubleValue();
    }

    public static Number decimalValue(String v, Number def) {

        if (v == null || v.length() == 0)
            return def;

        NumberFormat df = NumberFormat.getInstance();
        try {
            return df.parse(v);
        } catch (Exception e) {
            return def;
        }
    }

    public static boolean isZero(Number num) {
        if (num == null)
            return true;

        return num.intValue() == 0;
    }

    public static boolean isNotZero(Number num) {
        return !isZero(num);
    }

    /**
     * 判断一个对象是否为null或默认值
     * 
     * @param obj
     * @return
     */
    public static boolean isNullOrDefaultValue(Object obj) {
        if (obj == null)
            return true;

        if (obj instanceof String)
            return StringUtils.empty((String) obj);

        if (obj instanceof Integer) {
            Integer i = (Integer) obj;
            return i == null || i == 0;
        }

        if (obj instanceof Byte) {
            Byte i = (Byte) obj;
            return i == null || i == 0;
        }

        if (obj instanceof Short) {
            Short i = (Short) obj;
            return i == null || i == 0;
        }
        if (obj instanceof Long) {
            Long i = (Long) obj;
            return i == null || i == 0;
        }

        if (obj instanceof Float) {
            Float f = (Float) obj;
            return f == null || f == 0.0;
        }
        if (obj instanceof Double) {
            Double d = (Double) obj;
            return d == null || d == 0.0;
        }

        return false;
    }

    public static boolean isNullOrDefaultValue(Object obj, String defaultValue) {
        if (obj == null)
            return true;

        if (obj instanceof String && !obj.equals(defaultValue))
            return false;

        if (obj instanceof String && StringUtils.emptyTrimed((String) obj))
            return true;

        if (StringUtils.empty(defaultValue))
            return isNullOrDefaultValue(obj);

        if (obj instanceof String) {
            String d = (String) obj;
            return d.equals(defaultValue);
        }

        if (obj instanceof Integer) {
            Integer i1 = (Integer) obj;
            Integer i2 = intValue(defaultValue, Integer.MIN_VALUE);
            if (i2 == Integer.MIN_VALUE)
                return false;
            return i1.equals(i2);
        }

        if (obj instanceof Byte) {
            Byte s1 = (Byte) obj;
            Byte s2 = byteValue(defaultValue, Byte.MIN_VALUE);
            if (s2 == Byte.MIN_VALUE)
                return false;
            return s1.equals(s2);
        }

        if (obj instanceof Short) {
            Short s1 = (Short) obj;
            Short s2 = shortValue(defaultValue, Short.MIN_VALUE);
            if (s2 == Short.MIN_VALUE)
                return false;
            return s1.equals(s2);
        }

        if (obj instanceof Long) {
            Long l1 = (Long) obj;
            Long l2 = longValue(defaultValue, Long.MIN_VALUE);
            if (l2 == Long.MIN_VALUE)
                return false;
            return l1.equals(l2);
        }

        if (obj instanceof Float) {
            Float f1 = (Float) obj;
            Float f2 = floatValue(defaultValue, Float.MIN_VALUE);
            if (f2 == Float.MIN_VALUE)
                return false;
            return f1.equals(f2);
        }

        if (obj instanceof Double) {
            Double d1 = (Double) obj;
            Double d2 = doubleValue(defaultValue, Double.MIN_VALUE);
            if (d2 == Double.MIN_VALUE)
                return false;
            return d1.equals(d2);
        }

        return obj == null;
    }

    /**
     * 属性copy
     * 
     * @param dest 目标对象
     * @param src  源对象 
     */
    public static void copyProperties(Object dest, Object src) {
        if (src == null) {
            log.warn(" ### bean copy 源对象为null");
            return;
        }

        try {
            PropertyUtilsBean propUtils = new PropertyUtilsBean();
            PropertyDescriptor origDescriptors[] = propUtils.getPropertyDescriptors(src);
            for (PropertyDescriptor origDescriptor : origDescriptors) {
                String name = origDescriptor.getName();
                if ("class".equals(name)) {
                    continue;
                }
                if (propUtils.isReadable(src, name) && propUtils.isWriteable(dest, name)) {
                    try {
                        Object value = propUtils.getSimpleProperty(src, name);
                        // 不等于null的时候才设值,等于null时,忽略
                        if (value != null) {
                            BeanUtils.copyProperty(dest, name, value);
                        } else {
                            // 如果为空则,直接将其设置为null
                            ClassUtil.setFieldValue(dest, name, null);
                        }
                    } catch (NoSuchMethodException e) {
                        //ingore
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static void copyPropertiesIngoreNull(Object dest, Object src) {
        if (src == null) {
            log.warn(" ### bean copy 源对象为null");
            return;
        }

        try {
            PropertyUtilsBean propUtils = new PropertyUtilsBean();
            PropertyDescriptor origDescriptors[] = propUtils.getPropertyDescriptors(src);
            for (PropertyDescriptor origDescriptor : origDescriptors) {
                String name = origDescriptor.getName();
                if ("class".equals(name)) {
                    continue;
                }
                if (propUtils.isReadable(src, name) && propUtils.isWriteable(dest, name)) {
                    try {
                        Object value = propUtils.getSimpleProperty(src, name);
                        // 不等于null的时候才设值,等于null时,忽略
                        if (value != null) {
                            BeanUtils.copyProperty(dest, name, value);
                        }
                    } catch (NoSuchMethodException e) {
                        //ignore
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 将数据生成文件
     * 
     * @param sfilename
     *            文件名带路经
     * @param data
     *            需要保存数据
     * @param s_tab
     *            分隔号
     * @throws IOException
     */
    public static void writeFile(String sfilename, Object[][] data, String s_tab) throws IOException {
        PrintStream out = new PrintStream(new FileOutputStream(sfilename, false), true);

        int offset = sfilename.lastIndexOf("\\");
        if (offset > 0) {
            String s_path = sfilename.substring(0, offset);
            new File(s_path).mkdirs();
        }
        writeFile(out, data, s_tab);
    }

    public static void writeFile(OutputStream out, Object[][] data, String s_tab) throws IOException {
        BufferedOutputStream out1 = new BufferedOutputStream(out);
        writeFile(out1, data, s_tab);
    }

    /**
     * @param outputStream
     * @param data
     * @param s_tab
     * @throws IOException
     */
    public static void writeFile(FilterOutputStream outputStream, Object[][] data, String s_tab) throws IOException {
        int i, j;
        StringBuffer s_line;
        String tabSign = s_tab;
        if (s_tab == null || s_tab.trim().toUpperCase().equals("TAB")) {
            tabSign = "\t";
        }
        int arrayLeng = data.length;
        int dLeng = data[0].length;
        for (i = 0; i < arrayLeng; i++) {
            s_line = new StringBuffer();
            if (data[i][0] != null) {
                for (j = 0; j < dLeng; j++) {
                    if (data[i][j] == null) {
                        s_line.append("");
                    } else {
                        if (data[i][j] instanceof java.util.Date) {
                            s_line.append(DateTimeUtil
                                    .formatDate((java.util.Date) data[i][j], DateTimeUtil.DATE_FORMAT));
                        } else {
                            s_line.append(data[i][j]);
                        }
                    }
                    if (j < dLeng - 1) {
                        s_line.append(tabSign);
                    }
                }
                s_line.append(IOUtils.LINE_SEPARATOR);
                outputStream.write(s_line.toString().getBytes());
            }
        }
        outputStream.flush();
        outputStream.close();
    }

    public static double round(double source, int point) {
        return Math.round(source * Math.pow(10, point)) / Math.pow(10, point);
    }

    public static <T> Collection<T> extractToCollection(Class<T> cls, Collection<?> list, String fieldName) {
        Collection<T> col = new ArrayList<T>();

        for (Object obj : list) {
            T fieldValue = ClassUtil.getFieldValue(obj, fieldName, cls);
            if (fieldValue != null) {
                col.add(fieldValue);
            }
        }
        return col;
    }

    /**
     * 把用户输入的数以小数点为界分割开来，并调用 numFormat() 方法 进行相应的中文金额大写形式的转换
     * 
     * @param s
     *            String
     * @return 转换好的中文金额大写形式的字符串
     * @deprecated 使用NumberUtil.ChgMoney代替
     */
    @Deprecated
    public static String numberToChina(double d) {
        return NumberUtil.ChgMoney(d);
    }

}
